﻿using System;
using System.Collections.Generic;
using System.Net.Mail;
using System.Web.Security;
using System.Web.Mvc;
using P.InOut.NetMvc.Logging;
using BitFactory.Logging;
using dotNetMembership=System.Web.Security.Membership;

namespace P.InOut.NetMvc.Controllers
{
	public class FormsAuthenticationController : StarterKits.Mvc.Membership.Controllers.BaseFormsAuthenticationController
	{

		private const string SMTP_SERVER = "localhost";
		private const int SMTP_PORT = 25;
		private const string DEFAULT_FROM_ADDRESS = "example@domain.com";
        private InOutDatabaseLogger logger = new InOutDatabaseLogger();

		public FormsAuthenticationController()
		{

			//ToDo: Select which authentication mode will be presented by the /Login action.
			DefaultAuthenticationMode = AuthenticationMode.Forms; //### also available from via: /FormsAuthentication/FormsLogin
			//DefaultAuthenticationMode = AuthenticationMode.OpenID; //### also available from via: /FormsAuthentication/OpenIDLogin
			//DefaultAuthenticationMode = AuthenticationMode.WindowsLive; //### also available from via: /FormsAuthentication/WindowsLiveLogin

			//ToDo: Specify what authentication modes are allowed by the system.
			AllowedAuthenticationModes = new List<AuthenticationMode>{
				AuthenticationMode.Forms //### comment out to disallow Forms authentication
				//,AuthenticationMode.OpenID //### uncomment to allow OpenID authentication
				//,AuthenticationMode.WindowsLive //### uncomment to allow WindowsLive authentication
			};

        }

        #region OnAfterCreateUser

        //ToDo: Uncomment this method if you would like the first user that registers to be added to the Administrator role, otherwise delete it.
		/*protected override void OnAfterCreateUser( MembershipUser user, string password, string passwordAnswer, string returnUrl, System.Collections.Specialized.NameValueCollection form )
		{
			//### if this newly created user is the only user in the system, make them the administrator
			if( Membership.GetAllUsers().Count == 1 )
			{
				if( !Roles.RoleExists( "Administrator" ) )
					Roles.CreateRole( "Administrator" );
				Roles.AddUserToRole( user.UserName, "Administrator" );
			}
		}*/

		//ToDo: Uncomment this method if you are using OpenID authentication, otherwise delete it.
		/*protected override SimpleRegistrationRequestFields GetOpenIDRegistrationFields()
		{
			//ToDo: Return a SimpleRegistrationRequestFields struct specifying which OpenID registration fields you will request from the provider.
			SimpleRegistrationRequestFields fields = new SimpleRegistrationRequestFields();
			fields.FullName = SimpleRegistrationRequest.Request;
			fields.Email = SimpleRegistrationRequest.Request;
			return fields;
		}*/

		//ToDo: Uncomment this method if you are using OpenID authentication and want to specify a "whitelist" of allowed OpenID providers, otherwise delete it.
		/*protected override List<string> GetOpenIDWhitelist()
		{
			//ToDo: Return a List<string> of regular expressions to run against the OpenID identity. Each identity must match 1 or more of the expressions in this list.
			return null;
		}*/

		//ToDo: Uncomment this method if you are using OpenID authentication, otherwise delete it.
		/*protected override MembershipUser AssociateOpenIDToMembershipUser( string identity, SimpleRegistrationFieldValues registrationFields )
		{

			//ToDo: Implement this to use OpenID authentication.
			return null;

			//ToDo: Optionally, a default implementation has been provided below that automatically registers new OpenID users with the system using their OpenID url as their username; uncomment it to use it.
			//return RegisterOpenIDUserAutomatically( identity, registrationFields );

		}*/

		//ToDo: Uncomment this method if you are using OpenID authentication and want to use this default auto-register implementation, otherwise delete it.
		/*private MembershipUser RegisterOpenIDUserAutomatically( string identity, SimpleRegistrationFieldValues registrationFields )
		{

			//### try to get user
			MembershipUser user = Membership.GetUser( identity );

			//### if we didn't find user, create a new one
			if( user == null )
			{

				string password = Guid.NewGuid().ToString();
				MembershipCreateStatus status;
				user = Membership.CreateUser( identity, password, registrationFields.Email, password, password, true, out status );
				if( status != MembershipCreateStatus.Success )
					throw new MembershipCreateUserException( status.ToString() );

				//### if this newly created user is the only user in the system, make them the administrator
				if( Membership.GetAllUsers().Count == 1 )
				{
					if( !Roles.RoleExists( "Administrator" ) )
						Roles.CreateRole( "Administrator" );
					Roles.AddUserToRole( user.UserName, "Administrator" );
				}

			}
			else
			{
				user.Email = registrationFields.Email;
				Membership.UpdateUser( user );
			}

			//### implement this to use OpenID authentication
			return user;

		}*/

		//ToDo: Uncomment this method if you are using WindowsLive authentication, otherwise delete it.
        /*protected override MembershipUser AssociateWindowsLiveIDToMembershipUser( string userId )
        {
            //ToDo: Implement this to use Windows Live ID authentication.
            return null;
        }*/

        #endregion

        public JsonResult GetUserId()
        {
            MembershipUser user = dotNetMembership.GetUser();

            return this.Json(user);
        }

        private void LogAction(string message, BitFactory.Logging.LogSeverity severity, string userName)
        {
            logger.Execute("InOut", "Authentication", message, System.DateTime.Now,
                severity, userName);
        }

        protected override void OnAfterFormsAuthenticate(string userName, 
            string password, string rememberMe, string returnUrl)
        {
            // Log Successful Authentication
            LogAction("Success", LogSeverity.Info, userName);
        }

        protected override void OnFormsAuthenticateError(string userName, 
            string password, string rememberMe, string returnUrl, string error)
        {
            // Log Unsuccessful Authentication
            LogAction(error, LogSeverity.Info, userName);
        }

		protected override void OnAfterResetPassword( string email, 
            string userName, string newPassword )
		{
			//### send message
			SendMessage( email, DEFAULT_FROM_ADDRESS,

				//ToDo: Set the email's subject.
				"Your Password",

				//ToDo: Set the email's body.
				string.Format( "{0}, your password is: {1}.", userName, newPassword )

			);
		}

		protected override void OnAfterRetrievePassword( string email, 
            string userName, string newPassword )
		{
			//### send message
			SendMessage( email, DEFAULT_FROM_ADDRESS,

				//ToDo: Set the email's subject.
				"Your Password",

				//ToDo: Set the email's body.
				string.Format( "{0}, your password is: {1}.", userName, newPassword )

			);
		}

		private void SendMessage( string to, string from, string subject, string body )
		{
			//### build & send message
			MailMessage mailMessage = new MailMessage( from, to, subject, body );
			SmtpClient smtpClient = new SmtpClient( SMTP_SERVER, SMTP_PORT );
			smtpClient.Send( mailMessage );
		}

	}
}